package com.example.order;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.cloud.sentinel.SentinelProperties;
import com.alibaba.cloud.sentinel.datasource.RuleType;
import com.alibaba.cloud.sentinel.datasource.config.NacosDataSourceProperties;
import com.alibaba.csp.sentinel.datasource.WritableDataSource;
import com.alibaba.csp.sentinel.datasource.nacos.NacosWritableDataSource;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.transport.util.WritableDataSourceRegistry;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;

import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import static com.alibaba.cloud.sentinel.datasource.RuleType.DEGRADE;
import static com.alibaba.cloud.sentinel.datasource.RuleType.FLOW;

@EnableFeignClients //开启feign远程调用功能
@EnableDiscoveryClient //开启服务发现功能
@SpringBootApplication
public class OrderMainApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderMainApplication.class, args);
    }

    //1,项目启动就监听配置文件变化
    //2,发生变化后拿到变化的值
    //3,发送邮件
    //4,先导入优先,外部优先

    @Bean
    ApplicationRunner applicationRunner(NacosConfigManager nacosConfigManager, SentinelProperties sentinelProperties) {

        sentinelProperties.getDatasource().forEach((dataSourceName, dataSourcePropertiesConfiguration) -> {
            registerDataSourceBean(dataSourcePropertiesConfiguration.getNacos().getRuleType(), (NacosDataSourceProperties)dataSourcePropertiesConfiguration.getValidDataSourceProperties());
        });

        return args -> {
            System.out.println("---boot---");
            ConfigService configService = nacosConfigManager.getConfigService();
            configService.addListener("service-order.properties", "DEFAULT_GROUP", new Listener() {
                @Override
                public Executor getExecutor() {
                    return Executors.newFixedThreadPool(4);
                }

                @Override
                public void receiveConfigInfo(String configInfo) {
                    System.out.println("-变化的配置信处息:" + configInfo);
                }
            });
        };
    }

    public void registerDataSourceBean(RuleType type, NacosDataSourceProperties dataSourceProperties) {
        if (type.equals(FLOW) ) {
            WritableDataSource<List<FlowRule>> writableDataSource = new NacosWritableDataSource<>(
                    converProperties(dataSourceProperties), dataSourceProperties.getGroupId(), dataSourceProperties.getDataId(), this::encodeJson);
            WritableDataSourceRegistry.registerFlowDataSource(writableDataSource);
        } else if (type.equals(DEGRADE) ) {
            WritableDataSource<List<DegradeRule>> writableDataSource = new NacosWritableDataSource<>(
                    converProperties(dataSourceProperties), dataSourceProperties.getGroupId(), dataSourceProperties.getDataId(), this::encodeJson);
            WritableDataSourceRegistry.registerDegradeDataSource(writableDataSource);
        }
    }

    public Properties converProperties(NacosDataSourceProperties nacosDataSourceProperties) {
        Properties properties = new Properties();
        if (!StringUtils.isEmpty(nacosDataSourceProperties.getServerAddr())) {
            properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosDataSourceProperties.getServerAddr());
        }
        else {
            properties.setProperty(PropertyKeyConst.ENDPOINT, nacosDataSourceProperties.getEndpoint());
        }

        if (!StringUtils.isEmpty(nacosDataSourceProperties.getContextPath())) {
            properties.setProperty(PropertyKeyConst.CONTEXT_PATH, nacosDataSourceProperties.getContextPath());
        }
        if (!StringUtils.isEmpty(nacosDataSourceProperties.getAccessKey())) {
            properties.setProperty(PropertyKeyConst.ACCESS_KEY, nacosDataSourceProperties.getAccessKey());
        }
        if (!StringUtils.isEmpty(nacosDataSourceProperties.getSecretKey())) {
            properties.setProperty(PropertyKeyConst.SECRET_KEY, nacosDataSourceProperties.getSecretKey());
        }
        if (!StringUtils.isEmpty(nacosDataSourceProperties.getNamespace())) {
            properties.setProperty(PropertyKeyConst.NAMESPACE, nacosDataSourceProperties.getNamespace());
        }
        if (!StringUtils.isEmpty(nacosDataSourceProperties.getUsername())) {
            properties.setProperty(PropertyKeyConst.USERNAME, nacosDataSourceProperties.getUsername());
        }
        if (!StringUtils.isEmpty(nacosDataSourceProperties.getPassword())) {
            properties.setProperty(PropertyKeyConst.PASSWORD, nacosDataSourceProperties.getPassword());
        }
        return properties;
    }

    private <T> String encodeJson(T t) {
        return JSON.toJSONString(t);
    }

//    @Bean
//    ApplicationRunner applicationRunner() {
//        return new ApplicationRunner() {
//            @Override
//            public void run(ApplicationArguments args) throws Exception {
//
//            }
//        };
//    }
}
